package repo

import "fmt"

type ModuleLabelFilter struct {
	WhichRepo string // 哪个仓
	PlanFile  string // 安装计划文件
	PlanView  string // 计划视图
	Pattern   string // 版本模块匹配模式
	Regex     bool   // 是否采用正则匹配模式
}

func NewModuleLabelFilter() *ModuleLabelFilter {
	return &ModuleLabelFilter{
		WhichRepo: "",
		PlanFile:  "",
		PlanView:  "",
		Pattern:   "",
		Regex:     false,
	}
}

func (f *ModuleLabelFilter) Tidy(repo string) {
	if f.Pattern == "" || f.Pattern == "all" {
		if f.Regex {
			f.Pattern = ".*"
		} else {
			f.Pattern = "*"
		}
	}

	if f.WhichRepo == "" {
		f.WhichRepo = repo
	}
}

func SelectModuleLabels(filter *ModuleLabelFilter) ([]*ModuleLabel, error) {
	var allModuleLabels []*ModuleLabel = nil
	if filter.PlanFile != "" {
		// 如果指定了 plan file，就从该文件加载
		installPlan, err := ReadInstallPlanFile(filter.PlanFile, true)
		if err != nil {
			return nil, err
		}

		items := make([]*ModuleLabel, 0, 100)
		for _, item := range installPlan.items {
			if filter.PlanView == "" {
				items = append(items, item.Lable)
				continue
			}

			// 进一步按 env 筛选
			if _, exist := item.Views[filter.PlanView]; exist {
				items = append(items, item.Lable)
				continue
			}
		}

		allModuleLabels = items
	} else {
		// 确定仓库
		repoDir := DEVREPO
		statusFile := INSTALLED_STATUS_FILE
		if filter.WhichRepo == "pkgrepo" {
			repoDir = PKGREPO
			statusFile = VERSIONED_STATUS_FILE
		}

		// repoDir 必须存在
		if !PathIsDir(repoDir) {
			return nil, fmt.Errorf("the reponsitory path is invalid or not accessible: %v", repoDir)
		}

		// 如果没有指定就从环境中读取全部模块
		items, err := ListModuleLabels(repoDir, statusFile)
		if err != nil {
			return nil, err
		}

		allModuleLabels = items
	}

	// 创建一个匹配器
	var matcher Matcher = nil
	if filter.Regex {
		// 如果指定了采用正则表达式匹配
		m, err := NewRegexMatcher(filter.Pattern)
		if err != nil {
			return nil, err
		}
		matcher = m
	} else {
		// 如果没有指定正则表达式，那么就用通赔符号匹配
		m, err := NewWildcardMatcher(filter.Pattern)
		if err != nil {
			return nil, err
		}
		matcher = m
	}

	// 通过匹配器筛选出需要的数据
	result := make([]*ModuleLabel, 0, 100)
	for _, label := range allModuleLabels {
		if !matcher.Match(label.String()) {
			continue
		}

		result = append(result, label)
	}

	return result, nil
}
